package com.loong.android;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;

import androidx.annotation.Nullable;
import androidx.core.content.FileProvider;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * 应用操作工具类
 */
public class AppUtils {

    private final static int INSTALL_REQUEST_CODE = 6698;

    /**
     * 安装应用
     *
     * @param context 上下文
     * @param apkFilePath apk文件路径
     * @param event 安装事件回调
     */
    public static void install(Context context, String apkFilePath, InstallEvent event) {
        if (Build.VERSION.SDK_INT >= 26 && !context.getPackageManager().canRequestPackageInstalls()){
            //API26 即 Android8.0以上需要弹出一个"允许安装未知来源"的设置界面。
            Uri packageURI = Uri.parse("package:" + context.getPackageName());
            Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageURI);
            ((Activity) context).startActivityForResult(intent, INSTALL_REQUEST_CODE);
            if(context instanceof LonWin) {
                final LonWin win = (LonWin) context;
                final String listenName = AppUtils.class.getCanonicalName() + "installApp" + System.currentTimeMillis();
                win.addWinLifeListener(listenName, new WinLife() {
                    @Override
                    public void onActivityResult(int requestCode, int resultCode, @Nullable Intent intent) {
                        super.onActivityResult(requestCode, resultCode, intent);
                        if(requestCode != INSTALL_REQUEST_CODE) return;
                        win.removeWinLifeListener(listenName);
                        if(context.getPackageManager().canRequestPackageInstalls()) {
                            installApk(context, apkFilePath);
                            if(event != null) event.onComplete(true);
                        }else {
                            if(event != null) event.onComplete(false);
                        }
                    }
                });
            }
        }else {
            installApk(context, apkFilePath);
            if(event != null) event.onComplete(true);
        }
    }

    private static void installApk(Context context, String filePath) {
        if(context == null) return;
        File apkFile = new File(filePath);
        if (!apkFile.exists()) return;
        Intent i = new Intent(Intent.ACTION_VIEW);
        i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            Uri contentUri = FileProvider.getUriForFile(context, LonApp.getFileAuthority(), apkFile);
            i.setDataAndType(contentUri, "application/vnd.android.package-archive");
        }else {
            // 安装，如果签名不一致，可能出现程序未安装提示
            i.setDataAndType(Uri.fromFile(new File(apkFile.getAbsolutePath())),
                    "application/vnd.android.package-archive");
        }
        context.startActivity(i);
    }

    /**
     * 卸载应用
     *
     * @param context 上下文
     * @param packageName 应用包名
     */
    public static void uninstall(Context context, String packageName) {
        Uri uri = Uri.parse("package:" + packageName);
        Intent intent = new Intent(Intent.ACTION_DELETE, uri);
        context.startActivity(intent);
    }

    /**
     * 启动应用
     *
     * @param context 上下文
     * @param packageName 应用包名
     * @return 应用启动成功返回true，应用启动失败返回false
     */
    public static boolean launch(Context context, String packageName) {
        Intent intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
        if(intent == null) return false;
        context.startActivity(intent);
        return true;
    }

    /**
     * 判断应用是否拥有某个权限
     *
     * @param context 上下文
     * @param packageName 应用包名
     * @param permission 权限名称
     */
    public static boolean hasPermission(Context context, String packageName, String permission){
        return PackageManager.PERMISSION_GRANTED == context.getPackageManager().checkPermission(permission, packageName);
    }

    /**
     * 通过应用包名取得应用的包信息。
     *
     * @param context 上下文
     * @param packageName apk文件路径
     * @param flags 标志位，若为0则获取应用所有可获取的包信息，但是这样得到的信息量会很大，影响效率。
     *              所以需要尽量根据实际需要传递标志位。
     * @return 返回应用包信息对象，若应用未安装，则返回空(null)
     */
    public static AppInfo getAppInfo(Context context, String packageName, int flags) {
        try {
            PackageInfo info = context.getPackageManager().getPackageInfo(packageName, flags);
            return info == null ? null : new AppInfo(info);
        }catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 通过apk文件路径取得应用的包信息
     *
     * @param context 上下文
     * @param apkFilePath apk文件路径
     */
    public static AppInfo getAppInfoByPath(Context context, String apkFilePath, int flags) {
        try {
            PackageInfo info = context.getPackageManager().getPackageArchiveInfo(apkFilePath, flags);
            return info == null ? null : new AppInfo(info);
        }catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 取所有应用的包信息
     *
     * @param context 上下文
     * @param flags 获取包信息的标志位
     */
    public static AppInfo[] getAllAppInfo(Context context, int flags) {
        @SuppressLint("QueryPermissionsNeeded")
        List<PackageInfo> infoList = context.getPackageManager().getInstalledPackages(flags);
        if(infoList == null) return null;
        List<AppInfo> arr = new ArrayList<>();
        for (PackageInfo packageInfo : infoList) {
            arr.add(packageInfo == null ? null : new AppInfo(packageInfo));
        }
        return arr.toArray(new AppInfo[0]);
    }

    /**
     * 取所有系统应用的包信息
     *
     * @param context 上下文
     * @param flags 获取包信息的标志位
     */
    public static AppInfo[] getAllSystemAppInfo(Context context, int flags) {
        @SuppressLint("QueryPermissionsNeeded")
        List<PackageInfo> infoList = context.getPackageManager().getInstalledPackages(flags);
        if(infoList == null) return null;
        List<AppInfo> arr = new ArrayList<>();
        for (PackageInfo packageInfo : infoList) {
            if(packageInfo == null) continue;
            if((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) continue;
            arr.add(new AppInfo(packageInfo));
        }
        return arr.toArray(new AppInfo[0]);
    }

    /**
     * 取所有非系统应用的包信息
     *
     * @param context 上下文
     * @param flags 获取包信息的标志位
     */
    public static AppInfo[] getAllNonSystemAppInfo(Context context, int flags) {
        @SuppressLint("QueryPermissionsNeeded")
        List<PackageInfo> infoList = context.getPackageManager().getInstalledPackages(flags);
        if(infoList == null) return null;
        List<AppInfo> arr = new ArrayList<>();
        for (PackageInfo packageInfo : infoList) {
            if(packageInfo == null) continue;
            if((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) continue;
            arr.add(new AppInfo(packageInfo));
        }
        return arr.toArray(new AppInfo[0]);
    }

    /**
     * 安装应用的接口事件
     */
    public abstract static class InstallEvent {
        /**
         * 执行安装应用的操作完毕后回调，在安卓8(api26)及以上的系统版本，会自动申请"允许安装未知来源"的权限。
         * 获得权限后会继续操作安装，没有获得权限立即回调。
         *
         * @param res 结果，如果未获得"允许安装未知来源"的权限时，无法继续安装，结果得到false
         */
        public void onComplete(boolean res) {

        }
    }
}
